import { IVec2 } from "../../util/Defined";
import { MathUtil } from "../../util/MathUtil";
import { TypeUtil } from "../../util/TypeUtil";
import { Intersection } from "../Intersection";
import { Circle } from "../math/Circle";
import { Matrix } from "../math/Matrix";
import { Vec2 } from "../math/Vec2";
import { BaseShape, ShapeType } from "./BaseShape";
import { CircleShape } from "./CircleShape";

/**
 * 扇形图形
 * (适合用来做技能范围判定，不能用来做常规碰撞检测)
 */
export default class SectorShape extends BaseShape {

    readonly worldCircle = new Circle();
    readonly worldStartPos = new Vec2();
    readonly worldEndPos = new Vec2();
    worldStartRad: number;
    worldEndRad: number;

    /** 半径 */
    radius: number = 0;
    /** 起始弧度 */
    startRad: number = 0;
    /** 结束弧度 */
    endRad: number = MathUtil.RAD_180;

    /**
     * 设置扇形
     * @param radius 半径
     * @param startRad 起始弧度
     * @param endRad 结束弧度
     */
    setSector(radius: number, startRad: number, endRad: number) {
        this.radius = radius;
        this.startRad = startRad;
        this.endRad = endRad;
    }

    getType(): ShapeType {
        return ShapeType.sector;
    }

    update(pos: Readonly<IVec2>, trans?: Readonly<Matrix>): this {
        this.worldCircle.setPosTo(this);
        this.worldStartPos.setPosTo(this);
        this.worldEndPos.setPosTo(this);

        if (trans) {
            trans.transformPointN(this.worldCircle);
            const scale = Math.max(trans.getScaleX(), trans.getScaleY());
            this.worldCircle.radius = this.radius * scale;
            trans.transformPointN(this.worldStartPos.moveRad(this.startRad, this.radius));
            trans.transformPointN(this.worldEndPos.moveRad(this.endRad, this.radius));
        } else {
            this.worldCircle.radius = this.radius;
            this.worldStartPos.moveRad(this.startRad, this.radius);
            this.worldEndPos.moveRad(this.endRad, this.radius);
        }

        this.worldCircle.addPosTo(pos);
        this.worldStartPos.addPosTo(pos);
        this.worldEndPos.addPosTo(pos);
        this.worldStartRad = this.worldCircle.radTo(this.worldStartPos);
        this.worldEndRad = this.worldCircle.radTo(this.worldEndPos);

        const d = this.worldCircle.radius * 2;
        this.worldAABB.setRect(
            this.worldCircle.x - this.worldCircle.radius,
            this.worldCircle.y - this.worldCircle.radius,
            d, d
        );

        return this;
    }

    testCollide(shape: Readonly<BaseShape>): boolean {
        switch (shape.getType()) {
            case ShapeType.circle:
                const circle = (shape as CircleShape).worldCircle;
                if (Intersection.circleCircle2(this.worldCircle, circle)) {
                    const rad = this.worldCircle.radTo(circle);
                    if (MathUtil.radBetween(rad, this.worldStartRad, this.worldEndRad)) {
                        //圆心在角度内
                        return true;
                    }

                    if (Intersection.lineCircle(this.worldCircle, this.worldStartPos, circle)
                        || Intersection.lineCircle(this.worldCircle, this.worldEndPos, circle)) {
                        //圆与扇形两边相交
                        return true;
                    }
                }
                return false;
            // case ShapeType.rect:
            //     return Intersection.rectCircle2(shape.worldAABB, this.worldCircle);
            // case ShapeType.box:
            // case ShapeType.polygon:
            //     const polygon = (shape as BoxShape | PolygonShape).worldPolygon;
            //     return Intersection.rectRect(this.worldAABB, shape.worldAABB)
            //         && Intersection.polygonCircle2(polygon, this.worldCircle);
        }

        throw new Error(`未实现碰撞方法：${TypeUtil.getCls(this).name} -> ${TypeUtil.getCls(shape).name}`);
    }

}